package cn.virens.common.boot.dubbo.util;

import cn.hutool.core.util.URLUtil;
import cn.virens.common.util.core.Assert;
import cn.virens.common.util.exception.APIException;
import jakarta.servlet.http.HttpServletRequest;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.array.PrimitiveArrayUtil;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.regex.ReUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.split.SplitUtil;
import org.dromara.hutool.core.util.RandomUtil;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class SimpleUtil {
    private final static Pattern BASE_64_REG = Pattern.compile("^data:[\\w\\-;/]*base64,");
    private final static Pattern HTTP = Pattern.compile("^https?:.*", Pattern.CASE_INSENSITIVE);

    /**
     * 获取全部请求参数
     */
    public static Map<String, Object> map(HttpServletRequest request) {
        return MapUtil.map(request.getParameterMap(), (k, v) -> {
            return (Object) ArrayUtil.join(v, ",");
        });
    }

    /**
     * 遍历并修改内部属性
     */
    public static <T> List<T> format(List<T> list, Consumer<T> consumer) {
        for (T item : Assert.isNull(list)) {
            consumer.accept(item);
        }

        return list;
    }

    /**
     * 遍历并修改内部属性
     */
    public static <T, R> List<R> to(Collection<T> list, Function<T, R> fun) {
        List<R> answer = new ArrayList<>(list.size());

        for (T item : Assert.isNull(list)) {
            answer.add(fun.apply(item));
        }

        return answer;
    }

    /**
     * URL处理，非完整连接拼接对应的开头(Map)
     */
    public static String url(String cdnImg, Map<String, Object> item, String key) {
        return url(cdnImg, MapUtil.getStr(item, key));
    }

    /**
     * URL处理，非完整连接拼接对应的开头(Map)(逗号分割多个)
     */
    public static String url0(String cdnImg, Map<String, Object> item, String key) {
        return url0(cdnImg, MapUtil.getStr(item, key));
    }

    /**
     * URL处理，非完整连接拼接对应的开头(Map)(逗号分割多个)
     */
    public static List<String> urls(String cdnImg, Map<String, Object> item, String key) {
        return urls(cdnImg, MapUtil.getStr(item, key));
    }

    /**
     * 去掉base64中前部类型声明
     */
    public static String subBase64(String str) throws APIException {
        return ReUtil.delFirst(BASE_64_REG, str);
    }

    /**
     * URL处理，非完整连接拼接对应的开头(逗号分割多个)
     */
    public static List<String> urls(String start, String srcs) throws APIException {
        return CollUtil.map(split(srcs, ","), src -> url(start, src), true);
    }

    /**
     * URL处理，非完整连接拼接对应的开头(逗号分割多个)
     */
    public static String url0(String start, String srcs) throws APIException {
        return CollUtil.join(urls(start, srcs), ",");
    }

    /**
     * URL处理，非完整连接拼接对应的开头
     */
    public static String url(String start, String src) throws APIException {
        if (StrUtil.isEmpty(start) || StrUtil.isEmpty(src)) return null;

        if (src != null && !ReUtil.isMatch(HTTP, src)) {
            return path(start, src);
        } else {
            return src;
        }
    }

    /**
     * 从列表中随机抽取指定数量的不重复数据
     */
    public static <T> Stream<T> random(List<T> list, int limit) throws APIException {
        return Arrays.stream(random(list.size(), limit)).mapToObj(list::get);
    }

    /**
     * 生成不重复随机数组
     */
    public static int[] random(int max, int length) {
        int[] result = new int[len(max, length)];

        for (int i = 0; i < result.length; i++) {
            result[i] = name(result, max);
        }

        return result;
    }

    public static List<String> split(String string, String c) {
        if (string != null && !string.isEmpty()) {
            return SplitUtil.split(string, c);
        } else {
            return Collections.emptyList();
        }
    }

    private static String path(String path, String src) throws APIException {
        return URLUtil.normalize(path + "/" + src, true, true);
    }

    private static int name(int[] list, int max) {
        int index = RandomUtil.randomInt(1, max);

        while (PrimitiveArrayUtil.contains(list, index)) {
            index = RandomUtil.randomInt(1, max);
        }

        return index;
    }

    private static int len(int max, int length) {
        return length > max ? max : length;
    }

}
